<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="app">
        <h1>{{msg}}</h1>
    </div>
</body>

</html>
<script>
    // vue2的原理 

    //ES5里面 Object.defineProperty('劫持的对象','劫持的属性','选项')

    //劫持属性的目的就是为了添加set和get 存取器,在set函数中可以对视图进行响应更新

    let data = {
        msg: "韩梅梅",
        age: 30,
        hobby: '吃',
        person: {
            nickname: '李雷'
        }
    }

    function observer(obj) {  //负责对数据进行观察
        if (!obj || typeof obj !== 'object') return;

        Object.keys(obj).forEach(key => {
            defineReactive(obj, key, obj[key])
        })
    };

    function defineReactive(obj, key, value) { //核心的劫持逻辑,让数据变成响应式
        observer(value)
        Object.defineProperty(obj, key, {
            // configurable: true,
            // enumerable: true,//可以对这个对象的属性进行 for in遍历
            get() {
                //只要访问了被劫持的属性,那么就会触发这个函数
                console.log(key + '被访问了')
                return value
            },
            set(val) {
                //只要对被劫持了的属性进行访问,那么就会触发这个函数
                //val 就是 通过等号赋值的时候自动传入的新的值
                console.log(key + '被赋值了')
                // console.log(val)
                // data.msg = val
                value = val
            }
        })

    }

    observer(data)


    //对数组的处理就是hack了数组的7个方法

    //Object.defineProperty 能不能对数组进行响应? 可以的

    let arr = [1, 2, 3, 45]

    arr.forEach((item, index) => {
        Object.defineProperty(arr, index, {
            set(val) {
                console.log('arr' + index + '被修改了')
                item = val
            },
            get() {
                console.log('arr' + index + '被访问了')
                return item
            }
        })
    })

    //为什么不直接使用Object.defineProperty劫持数组?
    // defineProperty的缺陷
    //尤雨溪:因为性能和用户的收益不成正比
    //使用习惯的问题,我们很少会 arr[xx] = xx;都比较习惯于使用数组的方法开进行处理


    //vue2怎么处理数组? vue2对数组的原型方法进行改写,当调用7个方之一的时候,会触发改写的业务逻辑,对视图进行更新

    let arrMethods = ['shift', 'unshift', 'pop', 'push', 'reverse', 'sort', 'splice'];

    arrMethods.forEach(method => {
        Array.prototype[method] = function () { 
            console.log(123)
        }
    })
</script>